# int_handler.S
# By: Ariq Chowdhury
# Date created: March 17th 2011
# Date modified: April 2nd 2011 
# Modified by: 
#    Teresa Hume
#    Samuel Ferguson 
#    Spencer Clark 
	
.code32

	.extern test_interrupt_print
	.extern clock_handler
	.extern keyboard_handler
	.extern syscall_table
	.extern eoi
	.extern current_kstack
	.extern current_pstack
	.extern xprintf
	.extern schedule

.global kernel_panic

# Hardware interrupt service routines
.global hwint00
.global hwint01

# Software interrupt service routines
.global swint00 # syscall interrupt 

# Exceptions interrupt service routines
.global exc_div_by_zero
.global exc_debug
.global exc_non_maskable_interrupt
.global exc_breakpoint
.global exc_overflow
.global exc_bound_range_exceeded
.global exc_invalid_opcode
.global exc_device_not_avail
.global exc_double_fault
.global exc_coprocesssor_segment_overrun
.global exc_invalid_tss
.global exc_seg_not_present
.global exc_stack_seg_fault
.global exc_gen_protection_fault
.global exc_page_fault
.global exc_reserved
.global exc_x87fp
.global exc_alignment_check
.global exc_machine_check
.global exc_simd_fp
.global exc_security


#---------------#
# Hardware ISRs #
#===============#
	
hwint00:
	call save
	call clock_handler
	call schedule
	call restore

# esp = 001fffaf before the interrupt
hwint01: 
	call keyboard_handler
	iret

#---------------#
# Software ISRs #
#===============#

# space to store the data pushed on the stack by the interrupt
# (at the moment, we have to pop it off before performing a syscall)
int_state:
  .long 0
  .long 0
  .long 0

# swint00: system call handler
# index into the EAXth entry in the syscall_table
# and call the function there
swint00:
  pop (int_state)
  pop (int_state + 4)
  pop (int_state + 8)
  movl (syscall_table)(,%eax,4), %eax
  call %eax
  push %eax
  push (int_state + 8)
  push (int_state + 4)
  push (int_state)
  iret

#---------------------------------------------#
# Context Switch Utilities - save and restore #
#=============================================#

# function save:	
# Pre: there is a current process
# Post: current state is pushed to current->esp0
# Return: nothing
.global save
save:

	push %eax
  # grabbing the call address 
	movl 4(%esp), %eax
  # pushing general registers onto the stack 
	pusha
	# setting the new top of the kernel stack 
	movl %esp, current_kstack
	# pushing the return address onto the top of the stack 
	push %eax
	# returning to the caller 
	ret

# function restore:
# Pre: the interrupt handler is finished
# Post: restores a saved process' state from current->esp0
# Return: iret returns from interrupt
restore:
	# switch out the stack to the next proccess's stack 	
	movl current_kstack, %esp
	# pop the next process's general registers off its stack
	popa
	pop %eax # restoring the correct eax value 
	# return into the new current process 
	# ignoring the initial call address from call save 
	add $4, %esp
	#jmp .
	iret
	
# VBoxDbg> r
# eax=001fffcc ebx=001fff8f ecx=000b8500 edx=001fff1b esi=fee090fe edi=00000001
# eip=0000a1fd esp=001fff1b ebp=001fff67 iopl=0 nv up di pl nz na po nc
# cs=0008 ds=0010 es=0010 fs=0010 gs=0010 ss=0010               eflags=00000006
# 0008:0000a1fd eb fe                   jmp -002h (00000a1fdh)
# VBoxDbg> dd 001fff1b
#	             edi      esi      ebp      ?
# %00000000001fff1b: 00000001 fee090fe 001fff67 001fff3b
#	             ebx      eax?     ecx      ?
# %00000000001fff2b: 001fff8f 00000000 000b8320 0000a19f
#	             popeax   skipped  sp@iret   cs
# %00000000001fff3b: 00000000 0000a19f 00009f52 00000008
#	             flags    spinning spinning spinning...
# %00000000001fff4b: 00000216 0000b388 00000000 00009f00
	
#--------------------#
# Exception Handlers #
#====================#

# OMGWTFBBQSAUCE

  death: .asciz "\n\n                     Kernel Panic!\n\n"

.extern clear_screen
.extern printbomb

  kernel_panic:
  call clear_screen
  lea death, %ebx
  push %ebx
  push $0x4F
  call xprintf_c
  call printbomb
  pop %ebx
  pop %ebx
  pop %ebx
  call xprintf
  jmp .

  exc_div_by_zero:
  lea exc01, %ebx
  push %ebx
  call kernel_panic

  push exc21
  exc_debug:
  lea exc02, %ebx
  push %ebx
  call kernel_panic

  exc_non_maskable_interrupt:
  lea exc03, %ebx
  push %ebx
  call kernel_panic

  exc_breakpoint:
  lea exc04, %ebx
  push %ebx
  call kernel_panic

  exc_overflow:
  lea exc05, %ebx
  push %ebx
  call kernel_panic

  exc_bound_range_exceeded:
  lea exc06, %ebx
  push %ebx
  call kernel_panic

  exc_invalid_opcode:
  lea exc07, %ebx
  push %ebx
  call kernel_panic

  exc_device_not_avail:
  lea exc08, %ebx
  push %ebx
  call kernel_panic

  exc_double_fault:
  lea exc09, %ebx
  push %ebx
  call kernel_panic

  exc_coprocesssor_segment_overrun:
  lea exc10, %ebx
  push %ebx
  call kernel_panic

  exc_invalid_tss:
  lea exc11, %ebx
  push %ebx
  call kernel_panic

  exc_seg_not_present:
  lea exc12, %ebx
  push %ebx
  call kernel_panic

  exc_stack_seg_fault:
  lea exc13, %ebx
  push %ebx
  call kernel_panic

  exc_gen_protection_fault:
  lea exc14, %ebx
  push %ebx
  call kernel_panic

  exc_page_fault:
  lea exc15, %ebx
  push %ebx
  call kernel_panic

  exc_reserved:
  lea exc16, %ebx
  push %ebx
  call kernel_panic

  exc_x87fp:
  lea exc17, %ebx
  push %ebx
  call kernel_panic

  exc_alignment_check:
  lea exc18, %ebx
  push %ebx
  call kernel_panic

  exc_machine_check:
  lea exc19, %ebx
  push %ebx
  call kernel_panic

  exc_simd_fp:
  lea exc20, %ebx
  push %ebx
  call kernel_panic

  exc_security:
  lea exc21, %ebx
  push %ebx
  call kernel_panic

  exc01: .asciz "Divide by zero fault"
  exc02: .asciz "Debug fault" 
  exc03: .asciz "Non-maskable interrupt fault"
  exc04: .asciz "Breakpoint fault"
  exc05: .asciz "Overflow fault"
  exc06: .asciz "Bound range exceeded fault"
  exc07: .asciz "Invalid opcode fault"
  exc08: .asciz "Device not available fault"
  exc09: .asciz "Double fault"
  exc10: .asciz "Coprocessor segment overrun"
  exc11: .asciz "Invalid TSS"
  exc12: .asciz "Segment not present"
  exc13: .asciz "Stack segmentation fault"
  exc14: .asciz "General protection fault"
  exc15: .asciz "Page fault"
  exc16: .asciz "This should never be called. You have passed into another dimension."
  exc17: .asciz "x87 floating point fault"
  exc18: .asciz "Alignment check fault"
  exc19: .asciz "Machine check fault"
  exc20: .asciz "SIMD floating point fault"
  exc21: .asciz "Security fault"
